let class2type = {};
// 生成class2type映射
"Boolean Number String Function Array Date RegExp Object Error Symbol"
  .split(" ").map((item, index) => {
    class2type["[object " + item + "]"] = item.toLowerCase();
  });

/**
 * 类型判断
 * @param {*} object
 */
export const type = (obj) => {
  if (obj == null) {
    return obj + '';
  }
  return typeof obj === 'object' || typeof obj === 'function' ?
    class2type[Object.prototype.toString.call(obj)] || 'object' : typeof obj;
}

/**
 * 判断是否为对象
 * @param {*} object
 */
export const isObject = (obj) => {
  return type(obj) === 'object'
}

/**
 * 判断是否为数组
 * @param {*} array
 */
export const isArray = (arr) => {
  return type(arr) === 'array'
}

/**
 * 判断是否为空对象
 * @param {*} object 源对象
 */
export const isEmptyObject = (object) => {
  return Object.keys(object).length === 0
}

/**
 * 判断是否为空
 * @param {*} object 源对象
 */
export const isEmpty = (value) => {
  if (isArray(value)) {
    return value.length === 0
  }
  if (isObject(value)) {
    return isEmptyObject(value)
  }
  return !value
}

/**
 * 对象深拷贝
 * @param {*} obj 源对象
 */
export const deepCopy = (obj) => {
  if (typeof obj !== 'object') return;
  let newObj = isArray(obj) ? [] : {};
  for (let i in obj) {
    if (obj.hasOwnProperty(i)) {
      newObj[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i];
    }
  }
  return newObj;
}

/**
 * 防抖 (事件触发n秒后执行，继续触发重置n)
 * @param {*} func 源函数
 * @param {*} wait 等待时间
 * @param {*} immediate 是否立即执行
 */
export function debounce(func, wait, immediate) {
  var timeout, result;

  var debounced = function() {
    var context = this;
    var args = arguments;

    clearTimeout(timeout);
    if (immediate) {
      // 如果已经执行过，不再执行
      var callNow = !timeout;
      timeout = setTimeout(function() {
        timeout = null;
      }, wait)
      if (callNow) result = func.apply(context, args);
    } else {
      timeout = setTimeout(function() {
        func.apply(context, args);
      }, wait);
    }

    return result;
  }

  debounced.cancel = function() {
    clearTimeout(timeout);
    timeout = null;
  }

  return debounced;
}

/**
 * 节流 (每隔n秒，只行一次事件)
 * @param {*} func 源函数
 * @param {*} wait 等待时间
 * @param {*} immediate 是否立即执行
 */
export function throttle(func, wait, options) {
  var timeout, context, args, result;
  var previous = 0;
  if (!options) options = {};

  var later = function() {
    previous = options.leading === false ? 0 : new Date().getTime();
    timeout = null;
    func.apply(context, args);
    if (!timeout) context = args = null;
  }

  var throttled = function() {
    var now = new Date().getTime();
    if (!previous && options.leading === false) previous = now;
    var remaining = wait - (now - previous);
    context = this;
    args = arguments;
    if (remaining <= 0 || remaining > wait) {
      if (timeout) {
        clearTimeout(timeout);
        timeout = null;
      }
      previous = now;
      func.apply(context, args);
      if (!timeout) context = args = null;
    } else if (!timeout && options.trailing !== false) {
      timeout = setTimeout(later, remaining);
    }
  }

  throttled.cancel = function() {
    clearTimeout(timeout);
    previous = 0;
    timeout = null;
  }

  return throttled;
}








